﻿using System;
using System.Collections;
using System.Collections.Generic;
using wd2now.Framework.Legacy.Classes;
using wd2now.Framework.Legacy.Enums;
using wd2now.Framework.Legacy.Hands;
using wd2now.Model.Table;
using Card = wd2now.Model.Table.Card;
using Position = wd2now.Model.Table.Position;

namespace wd2now.Framework.Builder
{
    public class TableBuilder
    {
        OH_Wrapper Oh;

        public static managed_holdem_state mhs { get; set; }

        public TableBuilder(IntPtr getSymbolFromDll, IntPtr getPlayerName)
        {
            Oh = new OH_Wrapper(getSymbolFromDll, getPlayerName);
        }

        public void RefreshGlobalVar()
        {
            //Limits
            OH.bblind = Oh.GetSymbol(Symbols.bblind);
            OH.sblind = Oh.GetSymbol(Symbols.sblind);
            OH.ante = Oh.GetSymbol(Symbols.ante);

            //Chairs
            OH.MyChair = (int)Oh.GetSymbol(Symbols.userchair);
            OH.dealerchair = (int)Oh.GetSymbol(Symbols.dealerchair);
            OH.raischair = (int)Oh.GetSymbol(Symbols.raischair);

            OH.IsMyTurn = ((int)Oh.GetSymbol(Symbols.ismyturn) == 7);
            OH.BetRound = (Rounds)Oh.GetSymbol(Symbols.betround);



            OH.pot = Oh.GetSymbol(Symbols.pot);

            //updating card values
            OH.MyHand = new Hand();	//rank 2 ; ... ; 14=A suit 1=C ; 2=D ; 3=H ; 4=S           
            OH.MyHand.SetValues(OH.MyChair);

            OH.Board = new Board();
            OH.Board.SetBoardCards();

            OH.nstraightcommon = (int)Oh.GetSymbol(Symbols.nstraightcommon);
            OH.nstraightfillcommon = (int)Oh.GetSymbol(Symbols.nstraightfillcommon);

            OH.nrankedcommon = (int)Oh.GetSymbol(Symbols.nrankedcommon);
            OH.nsuitedcommon = (int)Oh.GetSymbol(Symbols.nsuitedcommon);
            OH.rankhicommon = (int)Oh.GetSymbol(Symbols.rankhicommon);

            OH.dealposition = (int)Oh.GetSymbol(Symbols.dealposition);
            OH.nplayersdealt = (int)Oh.GetSymbol(Symbols.nplayersdealt);
            OH.betposition = (int)Oh.GetSymbol(Symbols.betposition);
            OH.nplayersplaying = (int)Oh.GetSymbol(Symbols.nplayersplaying);


            OH.br = (int)Oh.GetSymbol(Symbols.br);
            OH.callposition = (int)Oh.GetSymbol(Symbols.callposition);
            OH.nopponentsbetting = (int)Oh.GetSymbol(Symbols.nopponentsbetting);
            OH.nraisbets = (int)Oh.GetSymbol(Symbols.nraisbets);
            OH.nopponentscalling = (int)Oh.GetSymbol(Symbols.nopponentscalling);
            OH.dealpositionrais = (int)Oh.GetSymbol(Symbols.dealpositionrais);
            OH.nopponentsplaying = (int)Oh.GetSymbol(Symbols.nopponentsplaying);

            OH.nbetstocall = (int)Oh.GetSymbol(Symbols.nbetstocall);

            OH.nstraightfill = (int)Oh.GetSymbol(Symbols.nstraightfill);
            OH.nsuited = (int)Oh.GetSymbol(Symbols.nsuited);
            OH.nstraight = (int)Oh.GetSymbol(Symbols.nstraight);
            OH.balance = Oh.GetSymbol(Symbols.balance);
            OH.call = OH.balance > 0 ? Math.Min(OH.balance, Oh.GetSymbol(Symbols.call)) : Oh.GetSymbol(Symbols.call);
            OH.bet = Oh.GetSymbol(Symbols.bet);
            double temp2 = Oh.GetSymbol(Symbols.ncallbets);
            OH.ncallbets = (int)temp2;
            OH.potplayer = (int)Oh.GetSymbol(Symbols.potplayer);

            OH.nchairsdealtleft = (int)(Oh.GetSymbol(Symbols.nchairsdealtleft));
            OH.isroyalflush = Convert.ToBoolean(Oh.GetSymbol(Symbols.isroyalflush));
            OH.isstraightflush = Convert.ToBoolean(Oh.GetSymbol(Symbols.isstraightflush));
            OH.pokervalcommon = (int)Oh.GetSymbol(Symbols.pokervalcommon);
            OH.nhandshi = (int)Oh.GetSymbol(Symbols.nhandshi);
            OH.isfourofakind = Convert.ToBoolean(Oh.GetSymbol(Symbols.isfourofakind));
            OH.isfullhouse = Convert.ToBoolean(Oh.GetSymbol(Symbols.isfullhouse));
            OH.pokerval = (int)Oh.GetSymbol(Symbols.pokerval);
            OH.pcbits = (int)Oh.GetSymbol(Symbols.pcbits);
            OH.trank = (int)Oh.GetSymbol(Symbols.trank);
            OH.isflush = Convert.ToBoolean(Oh.GetSymbol(Symbols.isflush));
            OH.ishiflush = Convert.ToBoolean(Oh.GetSymbol(Symbols.ishiflush));
            OH.nstraightflushfillcommon = (int)Oh.GetSymbol(Symbols.nstraightflushfillcommon);
            OH.srankbits = (int)Oh.GetSymbol(Symbols.srankbits);
            OH.srankhiplayer = (int)Oh.GetSymbol(Symbols.srankhiplayer);
            OH.isstraight = Convert.ToBoolean(Oh.GetSymbol(Symbols.isstraight));
            OH.rankloplayer = (int)Oh.GetSymbol(Symbols.rankloplayer);
            OH.isthreeofakind = Convert.ToBoolean(Oh.GetSymbol(Symbols.isthreeofakind));
            OH.rankhiplayer = (int)Oh.GetSymbol(Symbols.rankhiplayer);
            OH.ranklocommon = (int)Oh.GetSymbol(Symbols.ranklocommon);
            OH.istwopair = Convert.ToBoolean(Oh.GetSymbol(Symbols.istwopair));
            OH.trankcommon = (int)Oh.GetSymbol(Symbols.trankcommon);
            OH.isonepair = Convert.ToBoolean(Oh.GetSymbol(Symbols.isonepair));
            OH.ishipair = Convert.ToBoolean(Oh.GetSymbol(Symbols.ishipair));
            OH.ismidpair = Convert.ToBoolean(Oh.GetSymbol(Symbols.ismidpair));
            OH.islopair = Convert.ToBoolean(Oh.GetSymbol(Symbols.islopair));
            OH.prwinnow = Oh.GetSymbol(Symbols.prwinnow);
            OH.prwin = Oh.GetSymbol(Symbols.prwin);
            OH.prtie = Oh.GetSymbol(Symbols.prtie);
            OH.prlos = Oh.GetSymbol(Symbols.prlos);
            OH.mh_nouts = (int)Oh.GetSymbol(Symbols.mh_nouts);
            OH.callshort = Oh.GetSymbol(Symbols.callshort);
            OH.raisshort = Oh.GetSymbol(Symbols.raisshort);
            OH.ncardsunknown = (int)Oh.GetSymbol(Symbols.ncardsunknown);
            OH.bet4 = Oh.GetSymbol(Symbols.bet4);
            OH.ishandup = Convert.ToBoolean(Oh.GetSymbol(Symbols.ishandup));
            OH.randomround = Oh.GetSymbol(Symbols.randomround);
            OH.nplayersround = (int)Oh.GetSymbol(Symbols.nplayersround);

            OH.nbetsround = (int)Oh.GetSymbol(Symbols.nbetsround);
            OH.nbetsround1 = (int)Oh.GetSymbol(Symbols.nbetsround1);
            OH.nbetsround2 = (int)Oh.GetSymbol(Symbols.nbetsround2);
            OH.nbetsround3 = (int)Oh.GetSymbol(Symbols.nbetsround3);
            OH.nbetsround4 = (int)Oh.GetSymbol(Symbols.nbetsround4);

            OH.nranked = (int)Oh.GetSymbol(Symbols.nranked);
            OH.rankbits = (int)Oh.GetSymbol(Symbols.rankbits);
            OH.pokervalplayer = (int)Oh.GetSymbol(Symbols.pokervalplayer);
            OH.ncurrentbets = (int)Oh.GetSymbol(Symbols.ncurrentbets);
            OH.currentbet0 = Oh.GetSymbol(Symbols.currentbet0);
            OH.currentbet1 = Oh.GetSymbol(Symbols.currentbet1);
            OH.currentbet2 = Oh.GetSymbol(Symbols.currentbet2);
            OH.currentbet3 = Oh.GetSymbol(Symbols.currentbet3);
            OH.currentbet4 = Oh.GetSymbol(Symbols.currentbet4);
            OH.currentbet5 = Oh.GetSymbol(Symbols.currentbet5);
            OH.currentbet6 = Oh.GetSymbol(Symbols.currentbet6);
            OH.currentbet7 = Oh.GetSymbol(Symbols.currentbet7);
            OH.currentbet8 = Oh.GetSymbol(Symbols.currentbet8);
            OH.currentbet9 = Oh.GetSymbol(Symbols.currentbet9);
            OH.raisbits1 = (int)Oh.GetSymbol(Symbols.raisbits1);
            OH.raisbits2 = (int)Oh.GetSymbol(Symbols.raisbits2);
            OH.nopponentsraising = (int)Oh.GetSymbol(Symbols.nopponentsraising);

            OH.nopponentsseated = (int)Oh.GetSymbol(Symbols.nopponentsseated);
            OH.srankloplayer = (int)Oh.GetSymbol(Symbols.srankloplayer);
            OH.potcommon = Oh.GetSymbol(Symbols.potcommon);

            OH.dbg = Oh.GetSymbol(Symbols.didswag);
            OH.didswag = Oh.GetSymbol(Symbols.didswag) > 0;
            OH.didswaground1 = Oh.GetSymbol(Symbols.didswaground1) > 0;
            OH.didswaground2 = Oh.GetSymbol(Symbols.didswaground2) > 0;
            OH.didswaground3 = Oh.GetSymbol(Symbols.didswaground3) > 0;

            OH.didchec = Oh.GetSymbol(Symbols.didchec) > 0;
            OH.didraisround1 = Oh.GetSymbol(Symbols.didraisround1) > 0;
            OH.didraisround2 = Oh.GetSymbol(Symbols.didraisround2) > 0;
            OH.didraisround3 = Oh.GetSymbol(Symbols.didraisround3) > 0;

            OH.didcall = Oh.GetSymbol(Symbols.didcall) > 0;
            OH.didcallround1 = Oh.GetSymbol(Symbols.didcallround1) > 0;
            OH.didcallround2 = Oh.GetSymbol(Symbols.didcallround2) > 0;
            OH.didcallround3 = Oh.GetSymbol(Symbols.didcallround3) > 0;

            OH.opponentsplayingbits = (int)Oh.GetSymbol(Symbols.opponentsplayingbits);
            OH.balance0 = Oh.GetSymbol(Symbols.balance0);
            OH.balance1 = Oh.GetSymbol(Symbols.balance1);
            OH.balance2 = Oh.GetSymbol(Symbols.balance2);
            OH.balance3 = Oh.GetSymbol(Symbols.balance3);
            OH.balance4 = Oh.GetSymbol(Symbols.balance4);
            OH.balance5 = Oh.GetSymbol(Symbols.balance5);
            OH.balance6 = Oh.GetSymbol(Symbols.balance6);
            OH.balance7 = Oh.GetSymbol(Symbols.balance7);
            OH.balance8 = Oh.GetSymbol(Symbols.balance8);
            OH.balance9 = Oh.GetSymbol(Symbols.balance9);
            OH.nplayersround2 = (int)Oh.GetSymbol(Symbols.nplayersround2);
            OH.handrank169 = (int)Oh.GetSymbol(Symbols.handrank169);

            OH.strength_flush = (int)Oh.GetSymbol(Symbols.mh_str_flush);
            OH.strength_fullhouse = (int)Oh.GetSymbol(Symbols.mh_str_fullhouse);
            OH.strength_onepair = (int)Oh.GetSymbol(Symbols.mh_str_onepair);
            OH.strength_quads = (int)Oh.GetSymbol(Symbols.mh_str_quads);
            OH.strength_straight = (int)Oh.GetSymbol(Symbols.mh_str_straight);
            OH.strength_straightflush = (int)Oh.GetSymbol(Symbols.mh_str_strflush);
            OH.strength_trips = (int)Oh.GetSymbol(Symbols.mh_str_trips);
            OH.strength_twopair = (int)Oh.GetSymbol(Symbols.mh_str_twopair);

            OH.nplayersseated = (int)Oh.GetSymbol(Symbols.nplayersseated);
            OH.nchairs = (int)Oh.GetSymbol(Symbols.nchairs);


        }

        public Table BuildTable()
        {
            RefreshGlobalVar();

            var table = new Table
            {
                BigBlind = (int)OH.bblind,
                SmallBlind = (int)OH.sblind,
                Ante = (int)OH.ante,
                Round = (BettingRound)OH.BetRound,
                Players = GetPlayers(),
            };

            return table;
        }

        private List<Player> GetPlayers()
        {
            var players = new List<Player>();
            var opponentsPlaying = new BitArray(new int[] { OH.opponentsplayingbits });

            if (OH.balance0 > 0)
            {
                var player = new Player { Balance = (int)OH.balance0, Chair = 0, };
                players.Add(player);
            }
            if (OH.balance1 > 0)
            {
                var player = new Player { Balance = (int)OH.balance1, Chair = 1, };
                players.Add(player);
            }
            if (OH.balance2 > 0)
            {
                var player = new Player { Balance = (int)OH.balance2, Chair = 2, };
                players.Add(player);
            }
            if (OH.balance3 > 0)
            {
                var player = new Player { Balance = (int)OH.balance3, Chair = 3, };
                players.Add(player);
            }
            if (OH.balance4 > 0)
            {
                var player = new Player { Balance = (int)OH.balance4, Chair = 4, };
                players.Add(player);
            }
            if (OH.balance5 > 0)
            {
                var player = new Player { Balance = (int)OH.balance5, Chair = 5, };
                players.Add(player);
            }
            if (OH.balance6 > 0)
            {
                var player = new Player { Balance = (int)OH.balance6, Chair = 6, };
                players.Add(player);
            }
            if (OH.balance7 > 0)
            {
                var player = new Player { Balance = (int)OH.balance7, Chair = 7, };
                players.Add(player);
            }
            if (OH.balance8 > 0)
            {
                var player = new Player { Balance = (int)OH.balance8, Chair = 8, };
                players.Add(player);
            }
            if (OH.balance9 > 0)
            {
                var player = new Player { Balance = (int)OH.balance9, Chair = 9, };
                players.Add(player);
            }

            foreach (var player in players)
            {
                if (opponentsPlaying[player.Chair])
                {
                    player.Active = true;
                }
                player.Name = "Player" + player.Chair.ToString();
                if (player.Chair == OH.MyChair)
                {
                    player.Hero = true;
                    player.Name = "Hero";
                    player.Position = GetHeroPosition();

                    player.Cards = new List<Card>
                        {
                            new Card { Rank = OH.MyHand.FirstCard.Rank, Suit = (int)OH.MyHand.FirstCard.Suit, },
                            new Card { Rank = OH.MyHand.SecondCard.Rank, Suit = (int)OH.MyHand.SecondCard.Suit, },
                        };

                }
            }

            return players;
        }

        private Position GetHeroPosition()
        {
            if (OH.dealposition == 1) return Position.SmallBlind;
            if (OH.dealposition == 2) return Position.BigBlind;
            if (OH.nchairsdealtleft == 7) return Position.UnderTheGun;
            if (OH.nchairsdealtleft == 6) return Position.UnderTheGunPlus1;
            if (OH.nchairsdealtleft == 5) return Position.UnderTheGunPlus2;
            if (OH.nchairsdealtleft == 4) return Position.Middle1;
            if (OH.nchairsdealtleft == 3) return Position.Middle2;
            if (OH.nchairsdealtleft == 2) return Position.Middle3;
            if (OH.nchairsdealtleft == 1) return Position.CutOff;
            if (OH.nchairsdealtleft == 0) return Position.Button;

            throw new Exception("Unknown position");

        }
    }
}
